<?php
/**
 * 在线支付公共类
 *
 */


class onlinepayHandler {
	
	public $gateUrl;   //网关地址
	
	public $key;       //密钥
	
	public $parameters;//请求参数

    private $dbca;
	
	function __construct( &$dbca ) {
        $this->dbca = $dbca;
		$this->gateUrl = '';
		$this->parameters = array();
	}

    /**
     *
     * 接收在线支付返回参数
     * @param string $extend_field 扩展字段
     * @param string $bill_no 订单号字段名
     * @param string $total 支付总金额字段名
     * @param string $trade_no 交易流水号字段名
     * @param string $payTypeName 支付方式名称
     *
     */
    public function receiveParameter( $extend_field, $bill_no, $total, $trade_no, $payTypeName ) {
		$params = array(
            'payTypeName' => $payTypeName
        );
		if (!empty($_GET)) {
			foreach ($_GET as $k => $v) {
                if ($k == $extend_field) {
                    $arr = explode('|', $v);
                    $params['pcustID'] = $arr[0]; //客户号
                    $params['payTypeID'] = $arr[1];//支付方式ID
                } else if ($k == $bill_no) {
                    $params['bill_no'] = $v;
                } else if ($k == $total) {
                    $params['total'] = $v;
                } else if ($k == $trade_no) {
                    $params['trade_no'] = $v;
                } else {
                    $params[$k] = $v;
                }
			}
		}
		if (!empty($_POST)) {
			foreach ($_POST as $k => $v) {
                if ($k == $extend_field) {
                    $arr = explode('|', $v);
                    $params['pcustID'] = $arr[0]; //客户号
                    $params['payTypeID'] = $arr[1];//支付方式ID
                } else if ($k == $bill_no) {
                    $params['bill_no'] = $v;
                } else if ($k == $total) {
                    $params['total'] = $v;
                } else if ($k == $trade_no) {
                    $params['trade_no'] = $v;
                } else {
                    $params[$k] = $v;
                }
			}
		}
		$this->setParamsArray($params);
	}
	
	/**
	 * 根据键值和值保存参数
	 */
	public function setParameter($parameter, $parameterValue) {
		$this->parameters[$parameter] = $parameterValue;
	}
	
	/**
	 * 把一个数组保存到对象parameters属性里
	 *
	 * @param array $paramsArray
	 */
	public function setParamsArray($paramsArray) {
		$this->parameters = $paramsArray;
	}
	
	/**
	 * 根据key获得参数数值
	 */
	public function getParameter($parameter) {
		return $this->parameters[$parameter];
	}
	
	/**
	 * 获取所有参数
	 * @return array
	 */
	public function getAllParameters() {
		return $this->parameters;
	}
	
	/**
	 *设置入口地址,不包含参数值
	 */
	public function setGateURL($gateUrl) {
		$this->gateUrl = $gateUrl;
	}
	
	/**
	 * 获取密钥
	 */
	public function getKey() {
		return $this->key;
	}
	
	/**
	 * 设置密钥
	 */
	public function setKey($key) {
		$this->key = $key;
	}
	
	/**
	 * 普通订单支付
	 *
	 * @param object $dbca 数据库类实例
	 * @param int    $bill_no 订单号，默认为null
	 * @return bool
	 */
	public function billPay(&$dbca, $bill_no=null) {
		
		//定义变量
		$payTypeID = $this->getParameter('payTypeID');
		$total = $this->getParameter('total');
		$trade_no = $this->getParameter('trade_no');
		if (is_null($bill_no)) {
			$bill_no = $this->getParameter('bill_no');
		} else {
			$this->setParameter('bill_no', $bill_no);
		}
		
		try {
			
			//开启事务
			$dbca->beginTransaction();
			
			
			//查询普通订单
			$sqlstr = 'SELECT bill_no,bill_status,pay_status,deliver_name,deliver_email,billType FROM pa_bill_master WHERE bill_no = ' . $bill_no;
			$bill =& $dbca->stmt_query($sqlstr);
			$bill = $bill[0];
			
		
			//订单已生效或已支付
			if ($bill->bill_status == 3 || $bill->bill_status == 2 || $bill->bill_status == 5 || $bill->pay_status == 1) {
				throw new Exception(sprintf('订单%s在线支付失败', $bill_no));
			}
			
			
			//查询订单支付信息
			$sqlstr = sprintf('SELECT pay_amount FROM pa_bill_pay WHERE bill_no = %s AND payTypeID = %d', $bill_no, $payTypeID);
			$bill_pay =& $dbca->stmt_query($sqlstr);
			if (!$bill_pay) {
				throw new Exception(sprintf('订单在线支付时，订单号：%s，支付方式ID：%s，没有找到这条信息', $bill_no, $payTypeID));
			}
			$bill_pay = $bill_pay[0];
			
			
			//检查支付金额
			$total = round($total - $bill_pay->pay_amount, 2);
			if ($total < 0) {//支付返回的剩余金额小与订单支付方式金额
				throw new Exception(sprintf('订单在线支付时，订单号：%s，支付方式ID：%s，支付的金额小于该订单应付金额。支付金额：%s，应付金额：%s', 
											$bill_no, $payTypeID, $total, $bill_pay->pay_amount));
			}
			
			
			//更新订单支付状态信息
			$sqlstr = sprintf('UPDATE pa_bill_pay SET deduct_amount=%d,deduct_money=%d,paid_confirm_status=2,paid_confirmer="system",
							  paid_confirm_time="%s",pay_time="%s",pay_code="%s" WHERE bill_no = %s AND payTypeID = %d', $bill_pay->pay_amount,
							  $bill_pay->pay_amount, date(G_DEFAULT_DATETIME_FORMAT), date(G_DEFAULT_DATETIME_FORMAT), $trade_no,$bill_no, $payTypeID);
			$dbca->execute($sqlstr);
			
			
			//更新订单主表支付状态信息
			$sqlstr = 'UPDATE pa_bill_master SET pay_status = 1,payed_time="' . date(G_DEFAULT_DATETIME_FORMAT) . '" WHERE bill_no = ' . $bill_no;
			$dbca->execute($sqlstr);
			
			//添加订单轨迹
			$bill_trace = new entity('log_bill_trace');
			$bill_trace->creator = 'system';
			$bill_trace->bill_no = $bill_no;
			$bill_trace->package_no = null;
			$bill_trace->freight_company_id = null;
			$bill_trace->freight_company_name = null;
			$bill_trace->freight_websit = null;
			$bill_trace->freight_bill_no = null;
			$bill_trace->trace_time = date(G_DEFAULT_DATETIME_FORMAT);
			$bill_trace->trace_operator = 'system';
			$bill_trace->memo = '您的订单已付款，请等待发货';
			$dbca->save($bill_trace, 'shop');
			
			//关闭事务
			$dbca->commit();
			
		} catch (Exception $e) {
			
			//事务回滚
			$dbca->rollBack();
			//error_log($e->getMessage());
			return false;
			
		}

		return true;
		
	}
	
	/**
	 * 保存在线支付请求参数
	 *
	 * @param int $bill_no 订单号
	 * @param int $payTypeID 支付方式ID
	 * @param string $payTypeName 支付方式名称
	 * @param object $DBCA 数据库实例
	 */
	public function setSendParams($bill_no, $payTypeID, $payTypeName, &$DBCA, $allParameters=null){
		
		//获得所有请求参数数据
		if (is_null($allParameters)) {
			$allParameters = $this->getAllParameters();
		}
		$allParameters = print_r($allParameters, true);
		
		//使用订单号查询在线支付日志表
		$sql = 'SELECT bill_no,request_flg FROM log_onlinepay WHERE bill_no = ' . $bill_no;
		$billInfo = $DBCA->stmt_query($sql);
		
		if ($billInfo) {//已保存该订单的请求数据，更新
			
			if ($billInfo[0]->request_flg == 3)
				return -1;
			
			$sql = sprintf('UPDATE log_onlinepay SET payTypeID=%d,payTypeName="%s",request_str = "%s",timeStamp = "%s" WHERE bill_no = "%s"',
				   $payTypeID, $payTypeName, $allParameters,date(G_DEFAULT_DATETIME_FORMAT),$bill_no);
			$DBCA->execute($sql);
			
		} else {//未保存该订单的请求数据，保存
			
			$sql = sprintf('INSERT INTO log_onlinepay (uuid,timeStamp,creator,createTime,bill_no,payTypeID,payTypeName,request_str,beginTime,request_flg) 
				   VALUES ("%s","%s","%s","%s",%s,%d,"%s","%s","%s",1);',make_uuid(), date(G_DEFAULT_DATETIME_FORMAT), 'system', 
				   date(G_DEFAULT_DATETIME_FORMAT), $bill_no, $payTypeID, $payTypeName, $allParameters, date(G_DEFAULT_DATETIME_FORMAT));
			$DBCA->execute($sql);
			
		}
		
		return 1;
		
	}
	
	
	/**
	 * 保存在线支付服务端和客户端返回的数据
	 *
	 * @param int $bill_no 订单号
	 * @param int $responseType 1：服务端返回 2：客户端返回
	 * @param object $DBCA 数据库实例
	 * @param int $response_code 支付状态 2:失败 3：成功
	 */
	public function setReceiveParams($bill_no, $responseType, &$DBCA, $request_flg=null) {
		
		//获得所有返回参数数据
		$allParameters = $this->getAllParameters();
		$allParameters = print_r($allParameters, true);
		
		//检查在线支付日志表
		$sql = 'SELECT bill_no,request_flg FROM log_onlinepay WHERE bill_no = ' . $bill_no;
		$billInfo = $DBCA->stmt_query($sql);
		
		
		if ($billInfo) {
			
			if ($responseType == 1) {//服务端返回
				
				if ($request_flg == 3) {//支付成功
					$sql = sprintf('UPDATE log_onlinepay SET server_response_str="%s",request_flg=%d,endTime="%s",success_count=success_count+1 WHERE bill_no=%s',
					   	   $allParameters, $request_flg, date(G_DEFAULT_DATETIME_FORMAT), $bill_no);
					$DBCA->execute($sql);
					
					//订单已支付成功，不需要再进行支付
					if ($billInfo[0]->request_flg == 3) {
						return -1;
					}
					
				} else {			//支付失败
					
					$sql = sprintf('UPDATE log_onlinepay SET server_response_str="%s",request_flg =%d,endTime="%s",fail_count=fail_count+1 WHERE bill_no=%s',
					   	   $allParameters, $request_flg, date(G_DEFAULT_DATETIME_FORMAT), $bill_no);
					$DBCA->execute($sql);
					
				}
					   
			} else {//客户端返回
				
				$sql = sprintf('UPDATE log_onlinepay SET client_response_str="%s" WHERE bill_no=%s', $allParameters, $bill_no);
				$DBCA->execute($sql);
				
			}
			
		}
		
		return 1;
		
	}

}
